package com.nfha.algorithm.taskassign.main;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.nfha.algorithm.taskassign.Employee;
import com.nfha.algorithm.taskassign.GroupInfo;
import com.nfha.algorithm.taskassign.TaskAssignV2Exerciser;
import com.nfha.algorithm.taskassign.TaskInfo;


public class TaskAssignV2Main {

	
	public enum SkillsEnum{
		SKILL_A(1,"A"),
		SKILL_B(2,"B"),
		SKILL_C(3,"C"),
		SKILL_D(4,"D"),
		SKILL_E(5,"E");
		
		private int num;
		
		private String value;
		
		private SkillsEnum(int num, String value) {
			this.num = num;
			this.value = value;
		}
		
		public static String getValueByNum(int num){
			for(SkillsEnum skill:SkillsEnum.values() ){
				if(skill.num==num){
					return skill.value;
				}
			}
			return null;
		}
		
		
		public static String[] random(int min){
			//随机产生技能个数
			int max=SkillsEnum.values().length;
			int[] skillTotalNum = randomArray(min, max,1);
			
			
			//具体的技能编号
			int[] skillDetail = randomArray(min, max, skillTotalNum[0]);
			ArrayList<String> list = new ArrayList<String>();
			for (int skillNum : skillDetail) {
				String skill = SkillsEnum.getValueByNum(skillNum);
				list.add(skill);
				
			}
			return (String[]) list.toArray(new String[list.size()]);
			
		}
		
		
	}
	public enum PortCodeEnum{
		PORT_CODE_A(1,"A"),
		PORT_CODE_B(2,"B"),
		PORT_CODE_C(3,"C"),
		PORT_CODE_D(4,"D"),
		PORT_CODE_E(5,"E"),
		PORT_CODE_F(6,"F"),
		PORT_CODE_G(7,"G");
		
		private int num;
		
		private String value;
		
		private PortCodeEnum(int num, String value) {
			this.num = num;
			this.value = value;
		}
		
		public static String getValueByNum(int num){
			for(PortCodeEnum skill:PortCodeEnum.values() ){
				if(skill.num==num){
					return skill.value;
				}
			}
			return null;
		}
		
		
		public static String random(int min){
			//随机生成码头年编号
			int[] portCodeNum = randomArray(min, PortCodeEnum.values().length,1);
			
			return PortCodeEnum.getValueByNum(portCodeNum[0]);
			
		}
		
	}
	
	
	private static Map<String,Employee> loadEmployees() {

		List<Employee> employees = new ArrayList<>();

		employees.add(new Employee("1", "A", "C"));
		employees.add(new Employee("2", "A", "B", "D"));
		employees.add(new Employee("3", "E"));
		employees.add(new Employee("4", "A", "C", "D", "E"));
		employees.add(new Employee("5", "B"));
		employees.add(new Employee("6", "D"));
		employees.add(new Employee("7", "C"));
		employees.add(new Employee("8", "B", "D", "E"));

		
		Map<String,Employee> employessMap=TaskAssignV2Exerciser.toMap(employees);
		return employessMap;

	}
	
	
	/**
	 * @param min	随机数所在范围 最小
	 * @param max	随机数所在范围 最大
	 * @param n:随机数的个数
	 * @return
	 */
	public static int[] randomArray(int min, int max, int n) {
		int len = max - min + 1;

		if (max < min || n > len) {
			return null;
		}

		// 初始化给定范围的待选数组
		int[] source = new int[len];
		for (int i = min; i < min + len; i++) {
			source[i - min] = i;
		}

		int[] result = new int[n];
		Random rd = new Random();
		for (int i = 0; i < result.length; i++) {
			int index = rd.nextInt(source.length);
			// 将随机到的数放入结果集
			result[i] = source[index];
			// 将待选数组中被随机到的数，用待选数组(len-1)下标对应的数替换
			source[index] = source[source.length-1];
			source=Arrays.copyOf(source, source.length-1);
		}
		return result;
	}
	
	public static void main(String[] args) {

		//List<Employee> employees = loadEmployees();
		Map<String,Employee> employessMap=loadEmployees();
		
		
		List<TaskInfo> historyTaskInfos=new ArrayList<>();
	   //List<GroupInfo> historyGroupInfo=new ArrayList<GroupInfo>();
		
		for (int i = 0; i < 200; i++) {
			String port = PortCodeEnum.random(1);
			String[] needSkills = SkillsEnum.random(1);
			
			while(needSkills.length<2) {
				needSkills = SkillsEnum.random(1);
			}
			
			System.out.println("\n\n"+i+" 申请任务   监管点:" + port + "  技能:" + String.join(",", needSkills));
			
			
			
			
			//将选中的信息保存到集合中
			//historyGroupInfo.add(randGroupInfo);
			TaskInfo htaskInfo=new TaskInfo(i,port,needSkills);
			historyTaskInfos.add(htaskInfo);
			
			//2  增加X次（可设定，X>200）任务，任务所需要的技能为2到5个技能的随机，码头也随机，每次派单增加的任务都计入个人的待办。
			
			
			List<GroupInfo> groupInfos = TaskAssignV2Exerciser.calGroupInfo(employessMap.values(), htaskInfo.portCode, htaskInfo.skills);
			Map<String, GroupInfo> groupInfoMap = TaskAssignV2Exerciser.toMap(groupInfos);
			
			GroupInfo.print(groupInfos);

			htaskInfo.groupInfo = GroupInfo.draw(groupInfoMap);
			System.out.println("抽中：" + htaskInfo.groupInfo);
			
			for (Employee emp : htaskInfo.groupInfo.employees) {
				
				   emp.toDoTasks.add(htaskInfo);
			    
			}
			
			//
//			3.当个位数为5的派单（第5次、15次、25次。。。。）执行完毕后，对所有待办任务批量执行一次“待办转在办”的操作，具体规则为：
//			从派单序号从小到大运算，当派单执行人员组合中每个人的在办数小于等于5时，可以将这个待办任务接单；当一个组合中任意一人的在办数大于5时，这个任务不接单，待下一回合批量执行“待办转在办”的操作时再优先运算操作。
//			“待办转在办”运算后，显示这一组运算情况（哪几次的派单任务由待办转在办）和运算后每个人的待办、在办、已办、合计
			
			if((i+1)%10==5){
				for (TaskInfo taskInfo:historyTaskInfos) {
				  //已经接过的单就可以省略了
				  if(taskInfo.isAsigned)continue;
				  
				  
				  
				  
				  GroupInfo groupInfo=taskInfo.groupInfo;
				  String msg="接单成功    任务序号:"+taskInfo.seqNo+" 接单组:"+groupInfo.id;
				  
				  boolean isAssign=true;
				  for (Employee groupEmp : groupInfo.employees) {
					   
					    //for(Employee emp:employees) {
					     // if(!emp.id.equals(groupEmp.id))continue;
					      //待办转
					      Employee emp=employessMap.get(groupEmp.id);
					      if(emp.doingTasks.size()>5) {
					    	  //当一个组合中任意一人的在办数大于5时,该任务不接单
					    	  isAssign=false;
					    	  msg="接单拒绝   任务序号:"+taskInfo.seqNo+" 接单组:"+groupInfo.id+"  因为人员 "+emp.id+" 很忙 ,在办数:"+emp.doingTasks.size();
					    	  break;
					      }
					   
				  }
				  taskInfo.isAsigned=isAssign;
				  
				    
				    if(taskInfo.isAsigned) {
				    	for(Employee emp:groupInfo.employees) {
				    		 //Employee emp=employessMap.get(groupEmp.id);
						      //emp.updateCur(0,emp.doingTaskCount+emp.toDoTaskCount, emp.doneTaskCount, emp.portCode);
						     // emp.updateCur(emp.toDoTaskCount-1, emp.doingTaskCount+1, emp.doneTaskCount, emp.portCode);
						     emp.doingTasks.add(taskInfo); 
				    		 emp.toDoTasks.remove(taskInfo);
						 }
				    }
				  
				  System.out.println(msg);
				}
				
				
				System.out.println("=========待办转在办============");
				Employee.print(employessMap.values());
				
			}
			
			//当个位数为0的派单（第10次、20次、30次
			if((i+1)!=0 &&  (i+1)%10==0){
				//清空所有人员的临时任务
				for(Employee emp:employessMap.values()) {
					  
					  emp.tempTasks.clear();
				  }
				
				for (TaskInfo taskInfo:historyTaskInfos) {
					  //未接的单或已经完成的单就可以省略了
					  if(!taskInfo.isAsigned||taskInfo.isDone)continue;
					  
					  
					  
					  GroupInfo groupInfo=taskInfo.groupInfo;
					  String msg="办理完成    任务序号:"+taskInfo.seqNo+" 接单组:"+groupInfo.id;
					  boolean isDo=true;
					  for (Employee emp : groupInfo.employees) {
						    
						    ////for(Employee emp:employees) {
						    //  if(!emp.id.equals(groupEmp.id))continue;
						      //待办转
						     //Employee emp=employessMap.get(groupEmp.id); 
						      
						      if(!emp.canDoTask(taskInfo)) {
						    	  isDo=false;
						    	  msg="任务拒办   任务序号:"+taskInfo.seqNo+" 接单组:"+groupInfo.id ;
						    	  msg+="\n"+taskInfo.remark;
						    	  break;
						      }
						      
						   // }
						    
						    
						   
					  }
					  taskInfo.isDone=isDo;
					  
					  if(taskInfo.isDone) {
					    	for(Employee emp:groupInfo.employees) {
					    		//Employee emp=employessMap.get(groupEmp.id); 
							      
							      //emp.updateCur(emp.toDoTaskCount, emp.doingTaskCount-1, emp.doneTaskCount+1, taskInfo.portCode);
					    		  emp.doingTasks.remove(taskInfo);
							      emp.doneTasks.add(taskInfo);
							      emp.tempTasks.add(taskInfo);
							      emp.portCode=taskInfo.portCode;
							 }
					    }
					  
					  
					  System.out.println(msg);
					}
					
					
					System.out.println("=========待办转在办============");
					Employee.print(employessMap.values());
			}
			
		}

	}
	
	
}
